/*
 * Copyright (c) 2009 by ZDO Corporation.
 * Author: A. Onur Cinar
 * 
 * http://code.google.com/p/zdo-struts2
 * http://www.zdo.com
 * 
 * This file is part of ZDO Struts 2 Applications.
 *
 * ZDO-Struts2 is free software: you can redistribute it and/or
 * modify it under the terms of  the GNU General Public License
 * as published by the Free Software Foundation, either version
 * 3 of the License, or any later version.
 *
 * ZDO-Struts2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

package com.zdo.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import com.zdo.persistence.PersistenceAware;

/**
 * Abstract data access object. Provides basic methods
 * through the {@link EntityManager}.
 */
public abstract class AbstractDao<T>
{
	protected final Class<T> tClass;
	protected final EntityManager entityManager;

	/**
	 * Constructor.
	 * 
	 * @param tClass DBO class.
	 * @param entityManager entity manager.
	 */
	public AbstractDao (Class<T> tClass, EntityManager entityManager)
	{
		this.tClass = tClass;
		this.entityManager = entityManager;
	}
	
	/**
	 * Adds the given DBO.
	 * 
	 * @param t DBO object.
	 */
	public void add (T t)
	{
		entityManager.persist(t);
	}

	/**
	 * Finds single DBO based on the given id.
	 * 
	 * @param id DBO id.
	 * @return DBO instance.
	 */
	public T get (Object id)
	{
		T t = entityManager.find(tClass, id);
		if (t == null)
			throw new NoResultException();

		injectPersistence(t);
		
		return t;
	}

	/**
	 * Updates the DBO object.
	 * 
	 * @param t DBO object.
	 */
	public void update (T t)
	{
		entityManager.merge(t);
	}

	/**
	 * Removes the DBO object.
	 * 
	 * @param t DBO object.
	 */
	public void remove (T t)
	{
		entityManager.remove(t);
	}
	
	/**
	 * Gets the result list from the given query. Injects persistence 
	 * if DBO objects are {@link PersistenceAware}.
	 * 
	 * @param query query object.
	 * @return result list.
	 */
	@SuppressWarnings("unchecked")
	protected List<T> getResultList (Query query)
	{
		List<T> list = query.getResultList();
		
		injectPersistence(list);
		
		return list;
	}
	
	/**
	 * Injects the {@link EntityManager} instance into 
	 * {@link PersistenceAware} DBO object.
	 * 
	 * @param t DBO object.
	 */
	protected void injectPersistence (T t)
	{
		if (t instanceof PersistenceAware)
			((PersistenceAware) t).setEntityManager(entityManager);
	}
	
	/**
	 * Injects the {@link EntityManager} instance into 
	 * {@link PersistenceAware} DBO objects.
	 * 
	 * @param list DBO objects.
	 */
	protected void injectPersistence (List<T> list)
	{
		if ((list == null) || list.isEmpty())
			return;
		
		if (!(list.get(0) instanceof PersistenceAware))
			return;
		
		for (T t : list)
			((PersistenceAware) t).setEntityManager(entityManager);		
	}
}
